package com.tao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tao.mapper.MenuMapper;
import com.tao.pojo.User;
import com.tao.pojo.vo.Code;
import com.tao.pojo.vo.LoginUser;
import com.tao.pojo.vo.ResponseResult;
import com.tao.service.LoginService;
import com.tao.service.UserService;
import com.tao.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@Service
public class LoginServiceImpl implements LoginService {

    private AuthenticationManager authenticationManager;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private RedisTemplate redisTemplate;

    public LoginServiceImpl(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public HashMap<String, Object> login(User user) {
        HashMap<String, Object> map = new HashMap<>();
        /**使用 Authentication 密码校验
         Authentication authenticate = null;
         try {
         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
         authenticate = authenticationManager.authenticate(auth);
         } catch (AuthenticationException e) {
         e.printStackTrace();
         map.put("error","用户名或密码错误");
         return map;
         }
         * */

        /**自定义校验 */
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //拿到密码进行加密
        lqw.eq(User::getUsername, user.getUsername());
        User info = userService.getOne(lqw);
        if (ObjectUtils.isEmpty(info)) {
            map.put("error", "用户不存在！！！");
            return map;
        }
        // 使用passwordEncoder.matches 进行密码校验
        boolean matches =
                passwordEncoder.matches(user.getPassword(), info.getPassword());

        if (!matches) {
            map.put("error", "密码不正确！！！");
            return map;
        }

        String tokenId = info.getId().toString();
        String jwt = null;
        try {
            jwt = JwtUtil.createJWT(tokenId);
        } catch (Exception e) {
            e.printStackTrace();
            map.put("mag", e.getMessage());
            return map;
        }
        /* 数据库授权 */
        List<String> strings = menuMapper.selectPermsByUserId(info.getId());
        String str = strings.get(0); // 获取列表中的第一个元素，即字符串 "[system:admin]"
        String[] array = str.split(":"); // 使用冒号 ":" 分割字符串，得到数组

        // 将数据存到缓存
        redisTemplate.opsForValue().set("login:" + tokenId, new LoginUser(info, Arrays.asList(array)));

        map.put("code", 200);
        map.put("mag", "登录成功");
        map.put("token", jwt);
        return map;
    }

    public HashMap<String, Object> adminLogin(User user) {
        HashMap<String, Object> map = new HashMap<>();
        /**使用 Authentication 密码校验
         Authentication authenticate = null;
         try {
         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
         authenticate = authenticationManager.authenticate(auth);
         } catch (AuthenticationException e) {
         e.printStackTrace();
         map.put("error","用户名或密码错误");
         return map;
         }
         * */

        /**自定义校验 */
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //拿到密码进行加密
        lqw.eq(User::getUsername, user.getUsername());
        User info = userService.getOne(lqw);
        if (ObjectUtils.isEmpty(info)) {
            map.put("error", "用户不存在！！！");
            return map;
        }
        // 使用passwordEncoder.matches 进行密码校验
        boolean matches =
                passwordEncoder.matches(user.getPassword(), info.getPassword());

        if (!matches) {
            map.put("error", "密码不正确！！！");
            return map;
        }

        String tokenId = info.getId().toString();
        String jwt = null;
        try {
            jwt = JwtUtil.createJWT(tokenId);
        } catch (Exception e) {
            e.printStackTrace();
            map.put("mag", e.getMessage());
            return map;
        }
        /* 数据库授权 */
        List<String> strings = menuMapper.selectPermsByUserId(info.getId());
        String str = strings.get(0); // 获取列表中的第一个元素，即字符串 "[system:admin]"
        String[] array = str.split(":"); // 使用冒号 ":" 分割字符串，得到数组
        List<String> list = Arrays.asList(array);
        if (list.contains("admin")){
            map.put("code", 200);
            map.put("mag", "管理员登录成功！");
            map.put("token", jwt);
            redisTemplate.opsForValue().set("login:" + tokenId, new LoginUser(info, Arrays.asList(array)));
            return map;
        }else {
            map.put("code", Code.ERR);
            map.put("mag", "登录失败！你不是管理员！");
            map.put("token", jwt);
            return map;
        }
    }

    @Override
    public String logout() {
        //  SecurityContextHolder 拿到用户id并执行删除
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();
        Long id = user.getId();
        // 删除redis的数据
        redisTemplate.delete("login:" + id);
        return "success logout";
    }

    @Override
    public ResponseResult register(User user) {
        //验证账号密码是否为空（省略）
        if (ObjectUtils.isEmpty(user.getUsername())){
            return new ResponseResult(400,"账号密码必填！",null);
        }
        // 判断用户名是否存在
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getUsername,user.getUsername());
        User one = userService.getOne(lqw);
        if (!ObjectUtils.isEmpty(one)){
          return new ResponseResult(400,"用户名已存在!",null);
        }
        //密码加密存储
        String password = passwordEncoder.encode(user.getPassword());
        user.setPassword(password);
        // 绑定角色id 绑定创建人 绑定创建时间 身份
        user.setRoleId(2L);
        user.setUserType(1);
        //执行保存
        userService.save(user);
        //注册成功执行登录
        return new ResponseResult(200,"success!",null);
    }
}
